package org.example.word;

import org.apache.poi.common.usermodel.PictureType;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xwpf.usermodel.*;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

public class DocxReplaceUtil {

    /**
     * 替换docx中的指定字符串并保存
     * @param sourcePath 源docx文件路径
     * @param targetPath 替换后保存的路径
     * @throws IOException 处理文件时可能抛出的异常
     */
    public static void replaceAndSave(File sourcePath, String targetPath, List<ReplaceEntity> replaceEntities) throws IOException {
        // 读取源docx文件
        FileInputStream fis = new FileInputStream(sourcePath);
        XWPFDocument document = new XWPFDocument(fis);

        // 处理段落中的文本
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        // 改进的段落处理逻辑
        for (XWPFParagraph paragraph : paragraphs) {
            // 遍历并替换每个Run中的文本
            for (XWPFRun run : paragraph.getRuns()) {
                String text = run.getText(0);
                if (text != null) {
                    for (ReplaceEntity replaceEntity : replaceEntities) {
                        if (text.contains(replaceEntity.getKey())) {
                            text = text.replace(replaceEntity.getKey(), replaceEntity.getValue());
                        }
                    }
                }
                run.setText(text, 0);
            }
        }



        // 保存替换后的文档
        FileOutputStream fos = new FileOutputStream(targetPath);
        document.write(fos);

        // 关闭资源
        fos.close();
        document.close();
        fis.close();
    }
    public static void insertData(String inputPath, String outputPath,List<TableRow> tableRows) {

        int tableIndex = 0;                // 要操作的表格索引（从0开始）
        int insertPosition = 1;            // 在第1行后插入（0-based索引）
        int rowsToInsert = tableRows.size();              // 要插入的行数

        try (XWPFDocument doc = new XWPFDocument(Files.newInputStream(Paths.get(inputPath)))) {
            // 获取目标表格
            XWPFTable table = doc.getTables().get(tableIndex);
            if (table == null) {
                throw new RuntimeException("未找到索引为 " + tableIndex + " 的表格");
            }

            // 循环插入指定行数
            for (int i = 0; i < rowsToInsert; i++) {
                // 复制插入位置的行作为模板（确保样式一致）
                XWPFTableRow templateRow = table.getRow(insertPosition);
                XWPFTableRow newRow = table.insertNewTableRow(insertPosition + 1);
                List<String> rowData = new ArrayList<>();
                rowData.add(String.valueOf(rowsToInsert-i));
                rowData.add(tableRows.get(i).getQhmc());
                rowData.add(tableRows.get(i).getNhxm());
                rowData.add(tableRows.get(i).getNhdm());
                rowData.add(tableRows.get(i).getZwmc());
                rowData.add(String.valueOf(tableRows.get(i).getTbmj()));
                // 复制模板行的单元格样式和内容（可选：根据需求修改内容）
                List<XWPFTableCell> templateCells = templateRow.getTableCells();
                for (int j = 0; j < templateCells.size(); j++) {
                    XWPFTableCell templateCell = templateCells.get(j);
                    XWPFTableCell newCell = newRow.addNewTableCell();

                    // 复制单元格样式（边框、背景色等）
                    newCell.getCTTc().setTcPr(templateCell.getCTTc().getTcPr());

                    // 复制单元格内容（段落、文本）
                    List<XWPFParagraph> templateParagraphs = templateCell.getParagraphs();
                    for (XWPFParagraph p : templateParagraphs) {
                        XWPFParagraph newPara = newCell.addParagraph();
                        newPara.getCTP().setPPr(p.getCTP().getPPr()); // 复制段落样式
                        // 复制文本内容（这里示例为清空，可根据需求设置新内容）
                        newPara.createRun().setText(rowData.get(j));

                    }
                }
            }
           // 第二行删除
            table.removeRow(insertPosition);
            // 保存修改后的文档
            try (FileOutputStream out = new FileOutputStream(outputPath)) {
                doc.write(out);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 public static void insertData(String inputPath, String outputPath,List<TableRow> tableRows,String base64) {

        int tableIndex = 0;                // 要操作的表格索引（从0开始）
        int insertPosition = 1;            // 在第1行后插入（0-based索引）
        int rowsToInsert = tableRows.size();              // 要插入的行数

        try (XWPFDocument doc = new XWPFDocument(Files.newInputStream(Paths.get(inputPath)))) {
            // 获取目标表格
            XWPFTable table = doc.getTables().get(tableIndex);
            if (table == null) {
                throw new RuntimeException("未找到索引为 " + tableIndex + " 的表格");
            }

            // 循环插入指定行数
            for (int i = 0; i < rowsToInsert; i++) {
                // 复制插入位置的行作为模板（确保样式一致）
                XWPFTableRow templateRow = table.getRow(insertPosition);
                XWPFTableRow newRow = table.insertNewTableRow(insertPosition + 1);
                List<String> rowData = new ArrayList<>();
                rowData.add(String.valueOf(rowsToInsert-i));
                rowData.add(tableRows.get(i).getQhmc());
                rowData.add(tableRows.get(i).getNhxm());
                rowData.add(tableRows.get(i).getNhdm());
                rowData.add(tableRows.get(i).getZwmc());
                rowData.add(String.valueOf(tableRows.get(i).getTbmj()));
                // 复制模板行的单元格样式和内容（可选：根据需求修改内容）
                List<XWPFTableCell> templateCells = templateRow.getTableCells();
                for (int j = 0; j < templateCells.size(); j++) {
                    XWPFTableCell templateCell = templateCells.get(j);
                    XWPFTableCell newCell = newRow.addNewTableCell();

                    // 复制单元格样式（边框、背景色等）
                    newCell.getCTTc().setTcPr(templateCell.getCTTc().getTcPr());

                    // 复制单元格内容（段落、文本）
                    List<XWPFParagraph> templateParagraphs = templateCell.getParagraphs();
                    for (XWPFParagraph p : templateParagraphs) {
                        XWPFParagraph newPara = newCell.addParagraph();
                        newPara.getCTP().setPPr(p.getCTP().getPPr()); // 复制段落样式
                        // 复制文本内容（这里示例为清空，可根据需求设置新内容）
                        newPara.createRun().setText(rowData.get(j));

                    }
                }
            }
           // 第二行删除
            table.removeRow(insertPosition);

            //查找文档中的第一个图片，用base64图片替换
            replaceFirstPictureWithBase64(doc,base64);

            // 保存修改后的文档
            try (FileOutputStream out = new FileOutputStream(outputPath)) {
                doc.write(out);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据Base64数据前缀确定图片类型
     */
    private static PictureType determinePictureType(String base64Image) {
        if (base64Image.startsWith("data:image/png")) {
            return PictureType.PNG;
        } else if (base64Image.startsWith("data:image/jpeg") || base64Image.startsWith("data:image/jpg")) {
            return PictureType.JPEG;
        } else if (base64Image.startsWith("data:image/gif")) {
            return PictureType.GIF;
        } else if (base64Image.startsWith("data:image/bmp")) {
            return PictureType.BMP;
        } else {
            // 默认返回PNG
            return PictureType.PNG;
        }
    }
    /**
     * 用Base64图片数据替换文档中的第一个图片
     * @param base64Image Base64格式的图片数据
     */
    public static void replaceFirstPictureWithBase64(XWPFDocument document, String base64Image) {
        try {
            // 移除Base64前缀（如果有）

            if (base64Image.contains(",")) {
                base64Image = base64Image.substring(base64Image.indexOf(",") + 1);
            }
            // 3. 清理Base64数据
            base64Image = base64Image.replaceAll("\\s", "");
            // 解码Base64数据
            byte[] imageBytes = Base64.getDecoder().decode(base64Image);

                // 查找第一个图片
                XWPFPicture firstPicture = findFirstPicture(document,imageBytes);
                if (firstPicture == null) {
                    throw new RuntimeException("文档中未找到图片");
                }
                // 替换图片数据
                replacePictureData(firstPicture, imageBytes,document);


        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("替换图片失败: " + e.getMessage());
        }
    }
    /**
     * 查找文档中第一个图片
     */
    private static XWPFPicture findFirstPicture(XWPFDocument document, byte[] imageBytes) throws IOException, InvalidFormatException {
        // 遍历所有段落
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            // 遍历段落中的所有Run
            for (XWPFRun run : paragraph.getRuns()) {
                // 遍历Run中的所有图片
                List<XWPFPicture> pictures = run.getEmbeddedPictures();
                if (!pictures.isEmpty()) {
                    //设置宽度占满页面
                    return pictures.get(0); // 返回第一个图片
                }
            }
        }
        // 遍历所有表格（如果图片在表格中）
        return null;
    }

    /**
     * 替换图片数据
     * @param picture 原图片对象
     * @param newImageBytes 新图片字节数组
     */
    private static void replacePictureData(XWPFPicture picture, byte[] newImageBytes,XWPFDocument document) {
        try {
            // 获取原图片的关系数据
            XWPFPictureData oldPictureData = picture.getPictureData();
            PackagePart part = oldPictureData.getPackagePart();

            // 替换图片字节流
            part.clear();
            try (OutputStream os = part.getOutputStream();
                 ByteArrayInputStream newImageStream = new ByteArrayInputStream(newImageBytes)) {

                // 将新图片字节写入输出流
                byte[] buffer = new byte[1024];
                int len;
                while ((len = newImageStream.read(buffer)) != -1) {
                    os.write(buffer, 0, len);
                }
                os.flush();
            }

// 获取文档的实际页面宽度（考虑页边距）
//            CTSectPr sectPr = document.getDocument().getBody().getSectPr();
//            CTPageSz pageSize = sectPr.getPgSz();
//            long pageWidthTwips = pageSize.getW().longValue();
//// 将twips转换为厘米：1cm = 567 twips
//            double pageWidthCm = pageWidthTwips / 567.0;


        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("替换图片数据失败: " + e.getMessage());
        }
    }

}